package factory.one.service;

import factory.one.entity.Batch;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.PreparedStatementCreator;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.jdbc.support.GeneratedKeyHolder;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * @author sk.z
 * 2023/6/26
 * 产品批次
 **/
@Service
public class BatchService {

    private final JdbcTemplate jdbcTemplate;

    public BatchService(JdbcTemplate jdbcTemplate) {
        this.jdbcTemplate = jdbcTemplate;
    }

    public Long add(Batch batch) {
        PreparedStatementCreator preparedStatementCreator = con -> {
            PreparedStatement statement = con.prepareStatement(
                    "insert into batch(order_id,product_id,order_num,remark,price,produce_user) values(?,?,?,?,?,?)",
                    Statement.RETURN_GENERATED_KEYS);
            statement.setLong(1, batch.getOrderId());
            statement.setLong(2, batch.getProductId());
            statement.setInt(3, batch.getOrderNum());
            statement.setString(4, batch.getRemark());
            statement.setInt(5, batch.getPrice());
            statement.setString(6, batch.getProduceUsers());
            return statement;
        };
        GeneratedKeyHolder holder = new GeneratedKeyHolder();
        jdbcTemplate.update(preparedStatementCreator, holder);
        return holder.getKey() == null ? null : holder.getKey().longValue();
    }

    public int update(Batch batch) {
        return jdbcTemplate.update("update batch set product_id=? , order_num=? , price=? , remark=? where id=? ", ps -> {
            ps.setLong(1, batch.getProductId());
            ps.setInt(2, batch.getOrderNum());
            ps.setInt(3, batch.getPrice());
            ps.setString(4, batch.getRemark());
            ps.setLong(5, batch.getId());
        });
    }

    public int updateProduceIncrease(Long id, Integer produce, String userName) {
        Batch batch = getById(id);
        String produceUsers = batch.getProduceUsers();
        String mergeUsers = merge(produceUsers, userName);

        return jdbcTemplate.update("update batch set produce_num = produce_num + ? , produce_user = ? where id=? ", ps -> {
            ps.setInt(1, produce);
            ps.setString(2, mergeUsers);
            ps.setLong(3, id);
        });
    }

    public int updateSendAndRefund(Long id, Integer send, Integer refund) {
        return jdbcTemplate.update("update batch set send_num = ?, refund_num = ? where id=? ", ps -> {
            ps.setInt(1, send);
            ps.setInt(2, refund);
            ps.setLong(3, id);
        });
    }

    public int updatePrice(Long id, Integer price) {
        return jdbcTemplate.update("update batch set price = ? where id=? ", ps -> {
            ps.setInt(1, price);
            ps.setLong(2, id);
        });
    }

    public int updatePrice(List<Batch> batchList) {
        int count = 0;
        for (Batch b : batchList) {
            count += updatePrice(b.getId(), b.getPrice());
        }
        return count;
    }

    public int del(Long id) {
        return jdbcTemplate.update("update batch set status=0 where id = ?", ps -> ps.setLong(1, id));
    }

    public void updateList(Long orderId, List<Batch> batchList) {
        List<Batch> list = this.list(orderId);
        Map<Long, Batch> map = list.stream().collect(Collectors.toMap(Batch::getId, Function.identity(), (k1, k2) -> k2));
        for (Batch updateBatch : batchList) {
            if (map.containsKey(updateBatch.getId())) {
                update(updateBatch);
                map.remove(updateBatch.getId());
            } else {
                updateBatch.setOrderId(orderId);
                add(updateBatch);
            }
        }
        if (CollectionUtils.isEmpty(map)) {
            return;
        }
        for (Long delId : map.keySet()) {
            del(delId);
        }
    }

    public Batch getById(Long id) {
        return jdbcTemplate.queryForObject("select * from batch where id = ?", new BatchRowMapper(), id);
    }

    public List<Batch> list(Long orderId) {
        return jdbcTemplate.query("select * from batch where status=1 " + (Objects.isNull(orderId) ? "" : ("and order_id = " + orderId)), new BatchRowMapper());
    }

    private static class BatchRowMapper implements RowMapper<Batch> {
        @Override
        public Batch mapRow(ResultSet rs, int rowNum) throws SQLException {
            Batch batch = new Batch();
            batch.setId(rs.getLong("id"));
            batch.setOrderId(rs.getLong("order_id"));
            batch.setProductId(rs.getLong("product_id"));
            batch.setOrderNum(rs.getInt("order_num"));
            batch.setProduceNum(rs.getInt("produce_num"));
            batch.setSendNum(rs.getInt("send_num"));
            batch.setRefundNum(rs.getInt("refund_num"));
            batch.setRemark(rs.getString("remark"));
            batch.setPrice(rs.getInt("price"));
            batch.setProduceUsers(rs.getString("produce_user"));
            batch.setStatus(rs.getInt("status"));
            return batch;
        }
    }

    private static String merge(String major, String add) {
        if (StringUtils.hasText(major)) {
            String[] split = major.split(",");
            for (String s : split) {
                if (s.equals(add)) {
                    return major;
                }
            }
            return major + "," + add;
        } else {
            return add;
        }
    }

}
